﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
//using Moq;
using Microsoft.WindowsAzure.StorageClient;
using Microsoft.WindowsAzure;
using System.Configuration;

namespace AzureGames.Data.Implementation.Tests
{
    [TestClass]
    public class StatisticsRepositoryTest
    {
        [TestInitialize]
        public void Setup()
        {


        }
        [TestMethod]
        public void StatisticsInMemoryTests()
        {
            RunStatisticsTests(new AzureGames.Data.InMemory.StatisticsRepository(), new AzureGames.Data.InMemory.StatisticsRepository());
        }

        [TestMethod]
        public void StatisticsAzureTests()
        {
            CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) =>
            {
                // Provide the configSetter with the initial value
                configSetter(ConfigurationManager.AppSettings[configName]);
            });

            RunStatisticsTests(new AzureGames.Data.Implementation.GameStatisticsRepository(), new AzureGames.Data.Implementation.UserStatisticsRepository());
        }

        internal void RunStatisticsTests(IGameStatisticsRepository gameStatistics, IUserStatisticsRepository userStatistics)
        {
            string userId = "DF2AA2FD-6AA8-474F-B29B-BCCD8247D397";

            var gameStats = gameStatistics.GetGameStatistics(1, Model.Statistics.RANGE.ThisMonth);
            var userStats = userStatistics.GetUserStatistics(1, userId, Model.Statistics.RANGE.ThisMonth);

            int todayCreated = gameStats.Any(s => s.GameType == Model.Statistics.GameType.SinglePlayer && s.GameDefinitionID == 1 && s.Date == DateTime.Now.Date) 
                             ? gameStats.FirstOrDefault(s => s.GameType == Model.Statistics.GameType.SinglePlayer && s.GameDefinitionID == 1 && s.Date == DateTime.Now.Date).CreatedGames
                             : 0;
            int todayCancelled = gameStats.Any(s => s.GameType == Model.Statistics.GameType.SinglePlayer && s.GameDefinitionID == 1 && s.Date == DateTime.Now.Date)
                               ? gameStats.FirstOrDefault(s => s.GameType == Model.Statistics.GameType.SinglePlayer && s.GameDefinitionID == 1 && s.Date == DateTime.Now.Date).CancelledGames
                               : 0;
            int todayCompleted = gameStats.Any(s => s.GameType == Model.Statistics.GameType.SinglePlayer && s.GameDefinitionID == 1 && s.Date == DateTime.Now.Date)
                               ? gameStats.FirstOrDefault(s => s.GameType == Model.Statistics.GameType.SinglePlayer && s.GameDefinitionID == 1 && s.Date == DateTime.Now.Date).CompletedGames
                               : 0;
            int yesterdayCreated = gameStats.Any(s => s.GameType == Model.Statistics.GameType.SinglePlayer && s.GameDefinitionID == 1 && s.Date == DateTime.Now.Date.AddDays(-1))
                                 ? gameStats.FirstOrDefault(s => s.GameType == Model.Statistics.GameType.SinglePlayer && s.GameDefinitionID == 1 && s.Date == DateTime.Now.Date.AddDays(-1)).CreatedGames
                                 : 0;

            // start two games
            gameStatistics.AddGameStatistic(1, Model.Statistics.GameType.SinglePlayer, DateTime.Now.Date, 0);
            userStatistics.AddUserStatistic(1, Model.Statistics.GameType.SinglePlayer, DateTime.Now.Date, userId, 0);
            gameStatistics.AddGameStatistic(1, Model.Statistics.GameType.SinglePlayer, DateTime.Now.Date, 0);
            userStatistics.AddUserStatistic(1, Model.Statistics.GameType.SinglePlayer, DateTime.Now.Date, userId, 0);

            // complete one
            gameStatistics.RemoveGameStatistic(1, Model.Statistics.GameType.SinglePlayer, DateTime.Now.Date, 0);
            gameStatistics.AddGameStatistic(1, Model.Statistics.GameType.SinglePlayer, DateTime.Now.Date, 2);
            userStatistics.RemoveUserStatistic(1, Model.Statistics.GameType.SinglePlayer, DateTime.Now.Date, userId, 0);
            userStatistics.AddUserStatistic(1, Model.Statistics.GameType.SinglePlayer, DateTime.Now.Date, userId, 2);

            // cancel one
            gameStatistics.AddGameStatistic(1, Model.Statistics.GameType.SinglePlayer, DateTime.Now.Date, 3);
            userStatistics.AddUserStatistic(1, Model.Statistics.GameType.SinglePlayer, DateTime.Now.Date, userId, 3);
            gameStatistics.RemoveGameStatistic(1, Model.Statistics.GameType.SinglePlayer, DateTime.Now.Date, 0);
            userStatistics.RemoveUserStatistic(1, Model.Statistics.GameType.SinglePlayer, DateTime.Now.Date, userId, 0);

            // start one yesterday
            gameStatistics.AddGameStatistic(1, Model.Statistics.GameType.SinglePlayer, DateTime.Now.Date.AddDays(-1), 0);
            userStatistics.AddUserStatistic(1, Model.Statistics.GameType.SinglePlayer, DateTime.Now.Date.AddDays(-1), userId, 0);

            gameStats = gameStatistics.GetGameStatistics(1, Model.Statistics.RANGE.ThisMonth);
            userStats = userStatistics.GetUserStatistics(1, userId, Model.Statistics.RANGE.ThisMonth);

            Assert.AreEqual(todayCreated, gameStats.First(s => s.GameType == Model.Statistics.GameType.SinglePlayer && s.GameDefinitionID == 1 && s.Date == DateTime.Now.Date).CreatedGames);
            Assert.AreEqual(todayCancelled+1, gameStats.First(s => s.GameType == Model.Statistics.GameType.SinglePlayer && s.GameDefinitionID == 1 && s.Date == DateTime.Now.Date).CancelledGames);
            Assert.AreEqual(todayCompleted+1, gameStats.First(s => s.GameType == Model.Statistics.GameType.SinglePlayer && s.GameDefinitionID == 1 && s.Date == DateTime.Now.Date).CompletedGames);
            Assert.AreEqual(yesterdayCreated+1, gameStats.First(s => s.GameType == Model.Statistics.GameType.SinglePlayer && s.GameDefinitionID == 1 && s.Date == DateTime.Now.Date.AddDays(-1)).CreatedGames);

        }

    }
}

//        [TestMethod]
//        public void AddGameStatistic_CallsAddWhenNoGameStatsReturned()
//        {
//            //Arrange
//            var mockGameStatsTable = new Mock<IAzureTableRepository<TableServiceEntity>>();
//            var mockUserGameStatsTable = new Mock<IAzureTableRepository<TableServiceEntity>>();

//            StatisticsRepository rep = new StatisticsRepository(mockGameStatsTable.Object, mockUserGameStatsTable.Object);
//            var date = DateTime.Now;
           
//            //Act
//            rep.AddGameStatistic(1, Model.Statistics.GameType.MultiplePlayer, date, 0);

//            //Assert
//            mockGameStatsTable.Verify(n => n.Add(It.IsAny<TableServiceEntity>()), Times.Once());
//        }

//        [TestMethod]
//        public void AddGameStatistic_DoesNotCallAddWhenGameStatFound()
//        {
//            //Arrange
//            var mockGameStatsTable = new Mock<IAzureTableRepository<TableServiceEntity>>();
//            var mockUserGameStatsTable = new Mock<IAzureTableRepository<TableServiceEntity>>();

//            StatisticsRepository rep = new StatisticsRepository(mockGameStatsTable.Object, mockUserGameStatsTable.Object);
//            var date = DateTime.Now;
//            var gameDefID = 1;

//            List<TableServiceEntity> list = new List<TableServiceEntity>{new GameStatisticsEntity { GameDefinitionID = gameDefID, GameType = 1, Date = date }};
//            mockGameStatsTable.Setup(n => n.GetListByNamedProperty("GameStatistics", "Date", date)).Returns(list);

//            //Act
//            rep.AddGameStatistic(gameDefID, Model.Statistics.GameType.MultiplePlayer, date, 0);

           
//            //Assert
//            mockGameStatsTable.Verify(n => n.Add(It.IsAny<TableServiceEntity>()), Times.Never());
//        }

//        [TestMethod]
//        public void AddGameStatistic_CallsUpdateWithCorrectUpdatedValueState0()
//        {
//            //Arrange
//            var mockGameStatsTable = new Mock<IAzureTableRepository<TableServiceEntity>>();
//            var mockUserGameStatsTable = new Mock<IAzureTableRepository<TableServiceEntity>>();

//            StatisticsRepository rep = new StatisticsRepository(mockGameStatsTable.Object, mockUserGameStatsTable.Object);
//            var date = DateTime.Now;
//            var gameDefID = 1;
//            var gameStatisticsEntity = new GameStatisticsEntity { GameDefinitionID = gameDefID, GameType = 1, Date = date, CancelledGames = 0, CreatedGames = 0, CompletedGames = 0 };
//            List<TableServiceEntity> list = new List<TableServiceEntity> { gameStatisticsEntity };
//            mockGameStatsTable.Setup(n => n.GetListByNamedProperty("GameStatistics", "Date", date)).Returns(list);

//            //Act
//            rep.AddGameStatistic(gameDefID, Model.Statistics.GameType.MultiplePlayer, date, 0);


//            //Assert
//            mockGameStatsTable.Verify(n => n.Update(gameStatisticsEntity), Times.Once());
//            Assert.IsTrue(gameStatisticsEntity.CreatedGames == 1);
//        }

//        [TestMethod]
//        public void AddGameStatistic_CallsUpdateWithCorrectUpdatedValueState2()
//        {
//            //Arrange
//            var mockGameStatsTable = new Mock<IAzureTableRepository<TableServiceEntity>>();
//            var mockUserGameStatsTable = new Mock<IAzureTableRepository<TableServiceEntity>>();

//            StatisticsRepository rep = new StatisticsRepository(mockGameStatsTable.Object, mockUserGameStatsTable.Object);
//            var date = DateTime.Now;
//            var gameDefID = 1;
//            var gameStatisticsEntity = new GameStatisticsEntity { GameDefinitionID = gameDefID, GameType = 1, Date = date, CancelledGames = 0, CreatedGames = 0, CompletedGames = 0 };
//            List<TableServiceEntity> list = new List<TableServiceEntity> { gameStatisticsEntity };
//            mockGameStatsTable.Setup(n => n.GetListByNamedProperty("GameStatistics", "Date", date)).Returns(list);

//            //Act
//            rep.AddGameStatistic(gameDefID, Model.Statistics.GameType.MultiplePlayer, date, 2);


//            //Assert
//            mockGameStatsTable.Verify(n => n.Update(gameStatisticsEntity), Times.Once());
//            Assert.IsTrue(gameStatisticsEntity.CompletedGames == 1);
//        }

//        [TestMethod]
//        public void AddGameStatistic_CallsUpdateWithCorrectUpdatedValueState3()
//        {
//            //Arrange
//            var mockGameStatsTable = new Mock<IAzureTableRepository<TableServiceEntity>>();
//            var mockUserGameStatsTable = new Mock<IAzureTableRepository<TableServiceEntity>>();

//            StatisticsRepository rep = new StatisticsRepository(mockGameStatsTable.Object, mockUserGameStatsTable.Object);
//            var date = DateTime.Now;
//            var gameDefID = 1;
//            var gameStatisticsEntity = new GameStatisticsEntity { GameDefinitionID = gameDefID, GameType = 1, Date = date, CancelledGames = 0, CreatedGames = 0, CompletedGames = 0 };
//            List<TableServiceEntity> list = new List<TableServiceEntity> { gameStatisticsEntity };
//            mockGameStatsTable.Setup(n => n.GetListByNamedProperty("GameStatistics", "Date", date)).Returns(list);

//            //Act
//            rep.AddGameStatistic(gameDefID, Model.Statistics.GameType.MultiplePlayer, date, 3);


//            //Assert
//            mockGameStatsTable.Verify(n => n.Update(gameStatisticsEntity), Times.Once());
//            Assert.IsTrue(gameStatisticsEntity.CancelledGames == 1);
//        }

//        [TestMethod]
//        public void GetGameStatistics_ReturnsNullWhenRepositoryReturnsNull()
//        {
            
//            //Arrange
//            var mockGameStatsTable = new Mock<IAzureTableRepository<TableServiceEntity>>();
//            var mockGameStatsRepository = mockGameStatsTable.As<IGameStatisticsRepository>();
//            var mockUserGameStatsTable = new Mock<IAzureTableRepository<TableServiceEntity>>();

//            StatisticsRepository rep = new StatisticsRepository(mockGameStatsTable.Object, mockUserGameStatsTable.Object);
           
//            //Act
//            var result = rep.GetGameStatistics(1, Model.Statistics.RANGE.Today);

//            //Assert
//            Assert.IsNull(result);
            
//        }

//        [TestMethod]
//        public void GetGameStatistics_ReturnsValidValueWhenRepositoryReturnsValues()
//        {

//            //Arrange
//            var mockGameStatsTable = new Mock<IAzureTableRepository<TableServiceEntity>>();
//            //Get the mock to implement the other interface as well
//            var mockGameStatsRepository = mockGameStatsTable.As<IGameStatisticsRepository>();
//            var mockUserGameStatsTable = new Mock<IAzureTableRepository<TableServiceEntity>>();

//            var gameDef = 1;
//            var date = DateTime.Now;
//            var gameStatisticsEntity = new GameStatisticsEntity { GameDefinitionID = gameDef, GameType = 1, Date = date, CancelledGames = 0, CreatedGames = 0, CompletedGames = 0 };
//            List<TableServiceEntity> list = new List<TableServiceEntity> { gameStatisticsEntity };
//            mockGameStatsRepository.Setup(n => n.GetGameStatsByDateRangeAndGameDefinition(It.IsAny<string>(), It.IsAny<DateTime>(), gameDef)).Returns(list);

//            StatisticsRepository rep = new StatisticsRepository(mockGameStatsTable.Object, mockUserGameStatsTable.Object);
           
//            //Act
//            var result = rep.GetGameStatistics(1, Model.Statistics.RANGE.Today);

//            //Assert
//            Assert.IsTrue(result.Count() == 1);

//        }

//        [TestMethod]
//        public void AddUserGameStatistic_CallsGetGetUserGameStatOnce()
//        {
//            //Arrange
//            var mockGameStatsTable = new Mock<IAzureTableRepository<TableServiceEntity>>();
//            var mockUserGameStatsTable = new Mock<IAzureTableRepository<TableServiceEntity>>();
//            var mockUserGameRep = mockUserGameStatsTable.As<IUserGameStatisticsRepository>();

//            StatisticsRepository rep = new StatisticsRepository(mockGameStatsTable.Object, mockUserGameStatsTable.Object);
//            var date = DateTime.Now;

//            //Act
//            rep.AddUserStatistic(1, Model.Statistics.GameType.SinglePlayer, DateTime.Now, Guid.NewGuid(), 1);

//            //Assert
//            mockUserGameRep.Verify(n => n.GetUserGameStat(It.IsAny<string>(), 1, It.IsAny<DateTime>(), 0, It.IsAny<Guid>()), Times.Once());
//        }

//        [TestMethod]
//        public void AddUserGameStatistic_CallsAddWhenNoUserGameStatsReturned()
//        {
//            //Arrange
//            var mockGameStatsTable = new Mock<IAzureTableRepository<TableServiceEntity>>();
//            var mockUserGameStatsTable = new Mock<IAzureTableRepository<TableServiceEntity>>();
//            var mockUserGameRep = mockUserGameStatsTable.As<IUserGameStatisticsRepository>();

//            StatisticsRepository rep = new StatisticsRepository(mockGameStatsTable.Object, mockUserGameStatsTable.Object);
//            var date = DateTime.Now;

//            //Act
//            rep.AddUserStatistic(1, Model.Statistics.GameType.SinglePlayer, DateTime.Now, Guid.NewGuid(), 1);

//            //Assert
//            mockUserGameStatsTable.Verify(n => n.Add(It.IsAny<TableServiceEntity>()), Times.Once());
//        }

//        [TestMethod]
//        public void AddUserGameStatistic_DoesNotCallAddWhenUserGameStatFound()
//        {
//            //Arrange
//            var mockGameStatsTable = new Mock<IAzureTableRepository<TableServiceEntity>>();
//            var mockUserGameStatsTable = new Mock<IAzureTableRepository<TableServiceEntity>>();
//            var mockUserGameRep = mockUserGameStatsTable.As<IUserGameStatisticsRepository>();

//            StatisticsRepository rep = new StatisticsRepository(mockGameStatsTable.Object, mockUserGameStatsTable.Object);
//            var date = DateTime.Now;
//            var gameDefID = 1;
//            var playerID = Guid.NewGuid();
//            var entity =  new UserGameStatisticsEntity { GameDefinitionID = gameDefID, GameType = 1, Date = date } ;

//            mockUserGameRep.Setup(n => n.GetUserGameStat("GameStatistics", gameDefID, date, 0, playerID)).Returns(entity);

//            //Act
//            rep.AddUserStatistic(1, Model.Statistics.GameType.SinglePlayer, DateTime.Now, playerID, 1);


//            //Assert
//            mockGameStatsTable.Verify(n => n.Add(It.IsAny<TableServiceEntity>()), Times.Never());
//        }

//        [TestMethod]
//        public void AddUserGameStatistic_CallsUpdateWithCorrectUpdatedValueState0()
//        {
//            //Arrange
//            var mockGameStatsTable = new Mock<IAzureTableRepository<TableServiceEntity>>();
//            var mockUserGameStatsTable = new Mock<IAzureTableRepository<TableServiceEntity>>();
//            var mockUserGameRep = mockUserGameStatsTable.As<IUserGameStatisticsRepository>();

//            StatisticsRepository rep = new StatisticsRepository(mockGameStatsTable.Object, mockUserGameStatsTable.Object);
//            var date = DateTime.Now;
//            var gameDefID = 1;
//            var playerID = Guid.NewGuid();
//            var entity = new UserGameStatisticsEntity { GameDefinitionID = gameDefID, GameType = 1, Date = date };

//            mockUserGameRep.Setup(n => n.GetUserGameStat(It.IsAny<string>(), It.IsAny<int>(), It.IsAny<DateTime>(), It.IsAny<int>(), It.IsAny<Guid>())).Returns(entity);

//            //Act
//            rep.AddUserStatistic(1, Model.Statistics.GameType.SinglePlayer, DateTime.Now, playerID, 0);


//            //Assert
//            mockUserGameStatsTable.Verify(n => n.Update(entity), Times.Once());
//            Assert.IsTrue(entity.CreatedGames == 1);
//        }

//        [TestMethod]
//        public void AddUserGameStatistic_CallsUpdateWithCorrectUpdatedValueState2()
//        {
//            //Arrange
//            var mockGameStatsTable = new Mock<IAzureTableRepository<TableServiceEntity>>();
//            var mockUserGameStatsTable = new Mock<IAzureTableRepository<TableServiceEntity>>();
//            var mockUserGameRep = mockUserGameStatsTable.As<IUserGameStatisticsRepository>();

//            StatisticsRepository rep = new StatisticsRepository(mockGameStatsTable.Object, mockUserGameStatsTable.Object);
//            var date = DateTime.Now;
//            var gameDefID = 1;
//            var playerID = Guid.NewGuid();
//            var entity = new UserGameStatisticsEntity { GameDefinitionID = gameDefID, GameType = 1, Date = date };

//            mockUserGameRep.Setup(n => n.GetUserGameStat(It.IsAny<string>(), It.IsAny<int>(), It.IsAny<DateTime>(), It.IsAny<int>(), It.IsAny<Guid>())).Returns(entity);

//            //Act
//            rep.AddUserStatistic(1, Model.Statistics.GameType.SinglePlayer, DateTime.Now, playerID, 2);


//            //Assert
//            mockUserGameStatsTable.Verify(n => n.Update(entity), Times.Once());
//            Assert.IsTrue(entity.CompletedGames == 1);
//        }

//        [TestMethod]
//        public void AddUserGameStatistic_CallsUpdateWithCorrectUpdatedValueState3()
//        {
//            //Arrange
//            var mockGameStatsTable = new Mock<IAzureTableRepository<TableServiceEntity>>();
//            var mockUserGameStatsTable = new Mock<IAzureTableRepository<TableServiceEntity>>();
//            var mockUserGameRep = mockUserGameStatsTable.As<IUserGameStatisticsRepository>();

//            StatisticsRepository rep = new StatisticsRepository(mockGameStatsTable.Object, mockUserGameStatsTable.Object);
//            var date = DateTime.Now;
//            var gameDefID = 1;
//            var playerID = Guid.NewGuid();
//            var entity = new UserGameStatisticsEntity { GameDefinitionID = gameDefID, GameType = 1, Date = date };

//            mockUserGameRep.Setup(n => n.GetUserGameStat(It.IsAny<string>(), It.IsAny<int>(), It.IsAny<DateTime>(), It.IsAny<int>(), It.IsAny<Guid>())).Returns(entity);

//            //Act
//            rep.AddUserStatistic(1, Model.Statistics.GameType.SinglePlayer, DateTime.Now, playerID, 3);


//            //Assert
//            mockUserGameStatsTable.Verify(n => n.Update(entity), Times.Once());
//            Assert.IsTrue(entity.CancelledGames == 1);
//        }

//        [TestMethod]
//        public void GetUserGameStatistics_ReturnsNullWhenRepositoryReturnsNull()
//        {

//            //Arrange
//            var mockGameStatsTable = new Mock<IAzureTableRepository<TableServiceEntity>>();
//            var mockUserGameStatsTable = new Mock<IAzureTableRepository<TableServiceEntity>>();
//            var mockUserGamesRep = mockUserGameStatsTable.As<IUserGameStatisticsRepository>();
//            StatisticsRepository rep = new StatisticsRepository(mockGameStatsTable.Object, mockUserGameStatsTable.Object);

//            //Act
//            var result = rep.GetUserStatistics(1, Guid.NewGuid(), Model.Statistics.RANGE.Today);

//            //Assert
//            Assert.IsNull(result);

//        }

//        [TestMethod]
//        public void GetUserGameStatistics_ReturnsValidValueWhenRepositoryReturnsValues()
//        {

//            //Arrange
//            var mockGameStatsTable = new Mock<IAzureTableRepository<TableServiceEntity>>();
//            //Get the mock to implement the other interface as well
//            var mockUserGameStatsTable = new Mock<IAzureTableRepository<TableServiceEntity>>();
//            var mockUserGamesRep = mockUserGameStatsTable.As<IUserGameStatisticsRepository>();

//            var gameDef = 1;
//            var date = DateTime.Now;
//            var userGameStatisticsEntity = new UserGameStatisticsEntity { GameDefinitionID = gameDef, GameType = 1, Date = date, CancelledGames = 0, CreatedGames = 0, CompletedGames = 0 };
//            List<TableServiceEntity> list = new List<TableServiceEntity> { userGameStatisticsEntity };
//            mockUserGamesRep.Setup(n => n.GetUserGameStatsByDateRangeAndGameDefinitionAndPlayerID(It.IsAny<string>(), It.IsAny<DateTime>(), gameDef, It.IsAny<Guid>())).Returns(list);

//            StatisticsRepository rep = new StatisticsRepository(mockGameStatsTable.Object, mockUserGameStatsTable.Object);

//            //Act
//            var result = rep.GetUserStatistics(1, Guid.NewGuid(), Model.Statistics.RANGE.Today);

//            //Assert
//            Assert.IsTrue(result.Count() == 1);

//        }

//    }
//}
